<?php
namespace Pig\Controller;
use \Pig\Util\Page;

class OrderController extends BaseController {

    
    public $tbName = CONTROLLER_NAME;
    public $status = [
        '待付款','待发货','待收货','待评价','已完成','已取消','已失效','退款申请中','退款中','已拒绝','退款完成'
    ];
    /*
     * 列表页面
     */
    public function index() {
        //物流公司
        $Logistical = M('Logistical');
        $coms = $Logistical->where(array('deleted' => 0))->Field('id as "0",name as "1"')->select();
        $this->assign('coms',$coms);
        $this->assign('status',$this->status);
        $Obj = D($this->tbName.' as a'); //实例化对象
        $Where = "a.deleted=0";
        //下单时间
        if(I('request.start') && I('request.end')){
            $start = strtotime(I('request.start').' 00:00:00');
            $end = strtotime(I('request.end'),' 23:59:59');
            $Where .=  ' and a.crdate between'.$start.'and '.$end;
        }
        if(I('request.start') && !I('request.end')){
            $start = strtotime(I('request.start').' 00:00:00');
            $Where .= ' and a.crdate >='.$start;
        }
        if(!I('request.start') && I('request.end')){
            $end = strtotime(I('request.end').' 00:00:00');
            $Where .= ' and a.crdate <='.$end;
        }
         /*关键字查询*/   
        if (I('request.keyword')!='') {
            $I_keyword = trim(I('request.keyword'));
            $Where .= " and (a.order_num like '%" . $I_keyword . "%' OR a.phone LIKE '%".$I_keyword."%' OR a.name LIKE '%".$I_keyword."%')";
        }
         /*订单状态查询*/   
        if (I('request.status')) {
            $I_keyword = trim(I('request.status'));
            $Where .= " and (a.status = {$I_keyword})";
        }
        //控制分页显示条数
        if(I('post.limit_num')!=''){
            session('page_limit_num', I('post.limit_num'));
        }
        //控制列表排序
        $sorting = I('get.sorting') ? I('get.sorting') : 'a.id';
        $order = I('get.order') ? I('get.order') : 'desc';
        
        $limit_num = $_SESSION['page_limit_num'] ? $_SESSION['page_limit_num'] : 20;
        
        $Page = new Page($list_sum = $Obj->where($Where)->count(), $offset = $limit_num); // 实例化分页类 传入总记录数和每页显示的记录数
        $list = $Obj
                ->where($Where)
                ->order($sorting.' '.$order)
                ->limit($Page->firstRow . ',' . $Page->listRows)
                ->select();
        $this->assign('list', $list); // 赋值数据集
        $this->assign('page', $Page->show()); // 分页显示输出
        $this->display(); // 输出模板
    }

    public function complete(){
        if(IS_AJAX){
            try {
                $model = new \Think\Model;
                $model->startTrans();
                $id = I('request.id');
                $order = D($this->tbName);
                $orderInfo = $order->find($id);
                if($orderInfo['status'] == 2){
                    //完成订单状态
                    M($this->tbName)->where(array('id' => $id))->save(array('status' => 3,'remark' => I('param.remark')));
                }else{
                    $this->error('订单状态错误');
                }
                $model->commit();
                $this->success('录入成功',U(CONTROLLER_NAME.'/index?type=1'));
            } catch (\Exception $e) {
                $model->rollback();
                debug([$e->getmessage(),$e->getfile(),$e->getline()]);
                $this->error('录入失败');
            }
        }
        $this->display('completion');
    }

    /**
     * 拒绝退款
     */
    public function refuse(){
        try{
            $id = I('param.id');
            $model = new \Think\Model;
            $model->startTrans();
            $Obj = D($this->tbName);
            //修改订单状态
            $num = $Obj->where(array('id' => $id))->save(array('status' => 10,'tstamp' => time()));
            if($num){
                $model->commit();
                $this->success('操作成功',U(CONTROLLER_NAME.'/index'));
            }else{
                debug('修改订单状态失败');
                debug($Obj->_sql());
                $model->rollback();
                $this->error('操作失败',U(CONTROLLER_NAME.'/index')); 
            }
        }catch(\Exception $e){
            debug($e->getmessage());
            $model->rollback();
            $this->error('操作失败',U(CONTROLLER_NAME.'/index'));
        }
    }

    /**
     * 微信退款
     * @param   string  appid
     * @param   string  mchid
     * @param   string  key
     * @param   string  transaction_id   微信支付单号
     * @param   string  pay_price        订单金额
     */
    public function wxrefund(){
        try{
            $id = I('param.id');
            $model = new \Think\Model;
            $model->startTrans();
            $Obj = D($this->tbName);
            //获取订单详情
            $orderInfo = $Obj->find($id);
            /*数据整理请求接口*/
            $APIBase = new \Api\Model\BaseModel();
            $params = array(
                'appid' => C('Config.appid'),
                'mch_id' => C('Config.mchid'),
                'nonce_str' => $APIBase->CreateInviteCode(),
                'transaction_id' => $orderInfo['wx_num'],
                'out_refund_no' => date('YmdHis'),
                'total_fee' => $orderInfo['pay_price'] * 100,
                'refund_fee' => $orderInfo['pay_price'] * 100,
                'notify_url' =>  ($_SERVER['REQUEST_SCHEME']?:(strpos($_SERVER['SERVER_PROTOCOL'],'HTTPS')?'https':'http')).'://'.$_SERVER['HTTP_HOST'].'/api/refund/notify'
            );
            //证书
            $path = $_SERVER['DOCUMENT_ROOT'].'/'.C('CERT');
            //文件名
            $cert = 'apiclient_cert.pem';
            $key = 'apiclient_key.pem';
            $cert = $path . $cert;
            $key = $path . $key;
            //获取保存文件的物理路径
            $params = $this->getSignParams($params);
            $params = $this->createLinkString($params,C('Config.key'));
            $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
            $res = $this->curlPostSLL($url,$params,$key,$cert);
            if(!$res){
                $this->error('证书错误,请重新上传证书',U(CONTROLLER_NAME.'/index'));
            }
            /*返回结果验证*/
            $res = (array)simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
            debug($res);
            if($res['return_code'] == 'FAIL'){
                $this->error($res['return_msg'],U(CONTROLLER_NAME.'/index'));
            }
            if($res['result_code'] == 'FAIL'){
                $this->error($res['err_code_des'],U(CONTROLLER_NAME.'/index'));
            }
            //申请退款成功
            //修改订单状态
            $num = $Obj->where(array('id' => $id))->save(array('status' => 9,'tstamp' => time()));
            if($num){
                $model->commit();
                $this->success('操作成功',U(CONTROLLER_NAME.'/index'));
            }else{
                debug('修改订单状态失败');
                debug($Obj->_sql());
                $model->rollback();
                $this->error('操作失败',U(CONTROLLER_NAME.'/index')); 
            }
        }catch(\Exception $e){
            debug($e->getmessage());
            $model->rollback();
            $this->error('操作失败',U(CONTROLLER_NAME.'/index'));
        }
    }

    //使用证书
    public function curlPostSLL($url,$data,$key,$cert){
        //初始化curl句柄，
        $ch = curl_init();
        /*设置不使用CA证书*/
        $opt[CURLOPT_SSL_VERIFYHOST] = 2;
        $opt[CURLOPT_SSL_VERIFYPEER] = FALSE;
        curl_setopt_array($ch, $opt);
        //设置服务器返回的数据不直接输出，而是保留在curl_exec()的返回值中
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);

        /**--------微信退款证书---------**/
        //默认格式为PEM，可以注释
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT,$cert);
        //默认格式为PEM，可以注释
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY,$key);
        /**--------微信退款证书---------**/

        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_POST,true);
        $xml = '<xml>';
        foreach($data as $k => $val){
            $xml .= '<'.$k.'>'.$val.'</'.$k.'>';
        }
        $xml .= '</xml>';
        $data = $xml;
        curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        $return = curl_exec($ch);
        curl_close($ch);
        return $return;
    }

    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param $params
     * @param $mkey
     * @return string
     */
    public function createLinkString($params,$mkey){
        $arg  = "";
        foreach($params as $key => $val){
            $arg.=$key."=".$val."&";
        }
        $params['sign'] = strtoupper(MD5($arg.'key='.$mkey));
        return $params;
    }

    /**
     * 获取参与签名的参数
     * @param $params
     * @return array
     */
    public function getSignParams($params){
        $tmp = array();
        foreach($params as $key => $val){
            if($key !== 'sign' && $val !== ''){
                $tmp[$key] = $val;
            }
        }

        ksort($tmp);
        reset($tmp);

        return $tmp;
    }

    /*
     * 取消订单
     */

    public function editStatus() {
        $id = I('param.id');
        $type = I('param.type');
        $model = new \Think\Model;
        $model->startTrans();
        try {
            $order = D($this->tbName);
            $orderInfo = $order->find($id);
            if($orderInfo['status'] == 1){
                //修改订单状态
                M($this->tbName)->where(array('id' => $id))->save(array('status' => 6));
            }else{
                $this->error('订单状态错误',U(CONTROLLER_NAME.'/index?type='.$type));
            }
            $model->commit();
            $this->success('操作成功',U(CONTROLLER_NAME.'/index?type='.$type));
        } catch (\Exception $e) {
            $model->rollback();
            debug([$e->getmessage(),$e->getfile(),$e->getline()]);
            $this->success('操作失败',U(CONTROLLER_NAME.'/index?type='.$type));
        }
    }

    /*
     * 发货
     */

    public function send() {
        $id = I('param.id');
        $model = new \Think\Model;
        $model->startTrans();
        try {
            $order = D($this->tbName);
            $orderInfo = $order->find($id);
            if($orderInfo['status'] == 2){
                $data = I('request.');
                //获取对应选择的物流公司
                $info = M('Logistical')->find($data['logistics_id']);
                if(!$info){
                    $this->error('快递公司不存在');
                }
                //修改订单状态
                $param = [
                    'postage_name' => $info['name'],
                    'postage_code' => $info['com'],
                    'postage_num' => $data['postage_num'],
                    'status' => 3
                ];
                $flag = $order->where(array('id' => $id))->save($param);
                //对应商品库存减少
                $num = M('goods_info')->where(array('id' => $orderInfo['goods_info_id']))->setDec('stock',$orderInfo['num']);
                //改变优惠券的使用状态
                if($orderInfo['user_coupon_id']){
                    $status = M('user_coupon')->where(array('id' => $orderInfo['user_coupon_id']))->save(array('used_time' => time()));
                    if($status <= 0){
                        debug('修改优惠券的使用状态失败');
                        debug(M('user_coupon')->_sql());
                        $model->rollback();
                        $this->error('操作失败',U(CONTROLLER_NAME.'/index'));
                    }
                }
            }else{
                $this->error('订单状态错误');
            }
            if($flag && $num){
                $model->commit();
                $this->success('操作成功',U(CONTROLLER_NAME.'/index'));
            }else{
                debug([$order->_sql(),M('goods_info')->_sql()]);
                $model->rollback();
                $this->error('操作失败',U(CONTROLLER_NAME.'/index'));
            }
        } catch (\Exception $e) {
            $model->rollback();
            debug($e->getmessage());
            $this->success('操作失败',U(CONTROLLER_NAME.'/index'));
        }
    }

    //查看详情
    public function checkAchieve(){
        $id = I('get.id') ? I('get.id') : 0;
        if($id){
            $Obj = M($this->tbName);
            $info = $Obj->find($id);
            $param = [
                'com' => $info['postage_code'],
                'num' => $info['postage_num']
            ];
            $result = selectPostage($param);
            //有returnCode字段返回表示查询失败
            if(isset($result['returnCode'])){
                echo '<div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
                        <h5>'.$result['message'].'</h5>
                    </div>';
                exit;
            }
            //若返回state = 3表示该包裹已签收
            if($result['state'] == 3){
                //订单若为待收货状态则修改为待评价
                if($info['status'] == 3){
                    $Obj->startTrans();
                    $flag = $Obj->where(array('id' => $id))->save(array('status' => 4,'tstamp' => time()));
                    if(!$flag){
                        $Obj->rollback();
                        debug($Obj->_sql());
                    }
                    $Obj->commit();
                }
            }
            $html='';
            $html .= '
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
                        <h5>物流详情</h5>
                    </div>
                    <div class="portlet-body">
                        <table class="table table-striped table-hover table-bordered">
                            <tbody>';
            foreach ($result['data'] as $key => $value) {
                $html .= '<tr>';
                $html .= '<td>'.$value['context'].'</td>';
                $html .= '<td>'.$value['time'].'</td>';
                $html .= '</tr>';
            }
            $html .= '      </tbody>
                        </table>
                    </div>';
            echo $html;
        }
    }

    // Excel商品数据导出
    public function export(){
        try{
            import("Excel.PHPExcel");
            $Obj = D($this->tbName.' as a');
            $Where = ' a.deleted = 0';
            //下单时间
            if(I('request.start') && I('request.end')){
                $start = strtotime(I('request.start').' 00:00:00');
                $end = strtotime(I('request.end'),' 23:59:59');
                $Where .=  ' and a.crdate between'.$start.'and '.$end;
            }
            if(I('request.start') && !I('request.end')){
                $start = strtotime(I('request.start').' 00:00:00');
                $Where .= ' and a.crdate >='.$start;
            }
            if(!I('request.start') && I('request.end')){
                $end = strtotime(I('request.end').' 00:00:00');
                $Where .= ' and a.crdate <='.$end;
            }
             /*订单状态查询*/   
            if (I('request.status')) {
                $I_keyword = trim(I('request.status'));
                $Where .= " and (a.status = {$I_keyword})";
            }
            $list = $Obj
                    ->join(C('DB_PREFIX').'group as b ON a.group_id = b.id')
                    ->join(C('DB_PREFIX').'member as c on c.id = a.user_id')
                    ->where($Where)
                    ->field('a.status,a.goods_id,a.goods_name,a.group_id,a.id,a.crdate,a.pay_price,a.coupon_money,a.cost_money,a.num,c.nickname')
                    ->order('a.crdate DESC')
                    ->select();
                    //debug($Obj->_sql());
            //数据导出
            $Excel = new \PHPExcel();
            // 设置基本属性
            $Excel_pro = $Excel->getProperties();
            $Excel_pro->setCreator('admin') //设置创建者
                      ->setLastModifiedBy(date('Y-m-d H:i:s', time())) //设置时间
                      ->setTitle('订单数据') //设置标题
                      ->setSubject('导出') //备注
                      ->setDescription('订单数据导出'); //描述
                      //->setKeywords('商品') //关键字
                      //->setCategory('商品');//类别

            // sheet
            $Excel->setActiveSheetIndex(0);
            // sheet title
            $Excel->getActiveSheet(0)->setTitle('订单数据');

            $Excel->getActiveSheet()->setCellValue('A1', '商品id');
            $Excel->getActiveSheet()->setCellValue('B1', '商品名称');
            $Excel->getActiveSheet()->setCellValue('C1', '团购id');
            $Excel->getActiveSheet()->setCellValue('D1', '订单id');
            $Excel->getActiveSheet()->setCellValue('E1', '成交时间');
            $Excel->getActiveSheet()->setCellValue('F1', '实付金额');
            $Excel->getActiveSheet()->setCellValue('G1', '优惠券');
            $Excel->getActiveSheet()->setCellValue('H1', '用户');
            $Excel->getActiveSheet()->setCellValue('I1', '订单状态');
            $Excel->getActiveSheet()->setCellValue('J1', '快递名称');
            $Excel->getActiveSheet()->setCellValue('K1', '快递拼音');
            $Excel->getActiveSheet()->setCellValue('L1', '快递单号');
            foreach($list as $k => $v){
                $k = $k + 2;
                $Excel->getActiveSheet()->setCellValue('A' . $k, $v['goods_id']);
                $Excel->getActiveSheet()->setCellValue('B' . $k, $v['goods_name']);
                $Excel->getActiveSheet()->setCellValue('C' . $k, $v['group_id']);
                $Excel->getActiveSheet()->setCellValue('D' . $k, $v['id']);
                $Excel->getActiveSheet()->setCellValue('E' . $k,date('Y-m-d H:i:s',$v['crdate']));
                $Excel->getActiveSheet()->setCellValue('F' . $k, $v['pay_price']);
                $Excel->getActiveSheet()->setCellValue('G' . $k, $v['coupon_money']);
                $Excel->getActiveSheet()->setCellValue('H' . $k, $v['nickname']);
                $Excel->getActiveSheet()->setCellValue('I' . $k, self::orderStatus($v['status']));
                $Excel->getActiveSheet()->setCellValue('J' . $k, $v['postage_name']);
                $Excel->getActiveSheet()->setCellValue('K' . $k, $v['postage_code']);
                $Excel->getActiveSheet()->setCellValue('L' . $k, $v['postage_num']);
            }
            //写入

            $Excel_write = \PHPExcel_IOFactory::createWriter($Excel, 'Excel5');

            // 输出
            ob_end_clean();
            header('Pragma: public');
            header('Expires: 0');
            header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
            header('Content-Type:application/force-download');
            header('Content-Type:application/vnd.ms-execl;');
            header('Content-Type:application/octet-stream');
            header('Content-Type:application/download');
            header("Content-Disposition:attachment;filename=订单数据-".date('Y-m-d').".xls");
            header('Content-Transfer-Encoding:binary');
            $Excel_write->save('php://output'); 
        }catch(\Exception $e){
            debug($e->getmessage());
            $this->error('导出失败');
        }
    }

    // Excel数据导入数据库
    public function import(){
        import("Excel.PHPExcel");
        import("Excel.PHPExcel.Reader.Excel2007");

        $savePath = $this->Config['path_upload'] . MODULE_NAME . '/Excel/';

        if (! empty ( $_FILES ['import'] ['name'] )){

            $filename = $_FILES ['import'] ['tmp_name'];

            // 开始导入
            $PHPReader = new \PHPExcel_Reader_Excel2007();

            if (!$PHPReader->canRead($filename)) {
                $PHPReader = new \PHPExcel_Reader_Excel5();
                if (!$PHPReader->canRead($filename)) {
                    $this->error('没有Excel文件！');
                    exit;
                }
            }

            $PHPExcel = $PHPReader->load($filename);

            /**Read excel file in the first worksheet*/
            $currentSheet = $PHPExcel->getSheet(0);
            //$currentSheet = $PHPExcel->getSheet(0)->toArray();

            $allColumn = $currentSheet->getHighestColumn();
            $allRow = $currentSheet->getHighestRow();

            //echo $allColumn."|".$allRow."<br />";
            $sheetData = $PHPExcel->getActiveSheet()->toArray(null, true, true, true);
            
            //倒序导入
            //arsort($sheetData);
            //echo count($sheetData);

            /****set title begin****/
            //$headerKey = array_flip($sheetData[1]);
            $Obj = M($this->tbName);
            $message = [];
            foreach ($sheetData as $k => $v) {
                //k等于1为字段标题 不导入数据库
                if($k != 1){
                    //物流公司及单号缺失不导入
                    if($v['J'] && $v['K'] && $v['L']){
                        //已发货的订单不重复导入
                        $info = $Obj->find($v['D']);
                        if(!$info){
                           $message[] = '订单id为：'.$v['D'].'的订单数据不存在'; 
                        }else{
                            //只导入订单状态为待发货的数据
                            if($info['status'] == 2){
                               $rs = $Obj->where(array('id' => $v['D']))->save(array('status' => 3,'tstamp' => time(),'postage_name' => $v['J'],'postage_code' => $v['K'],'postage_num' => $v['L']));
                                if(!$rs){
                                    debug($Obj->_sql());
                                    $message[] = '订单id为：'.$v['D'].'的订单导入失败';
                                } 
                            }
                        }
                            
                    }else{
                        $message[] = '订单id为：'.$v['D'].'的订单,物流信息不完整';
                    }
                }
            }
            unlink($filename);
            if($message){
                $message = implode(';', $message);
            }else{
                $message = '导入成功';
            }
            $this->success ($message,U(CONTROLLER_NAME.'/index'));
            exit;
        }else{
            $this->error('请选择导入文件！');
        }
    }

    protected static function orderStatus($index){
        static $status = ['待支付','待发货','待收货','待评价','已完成','已取消','已失效','退款申请中','退款中','已拒绝','退款完成'];
        return $status[$index -1]?:'未知';
    }
}

?>